package model

import (
	"time"

	"bmember/pkg/util"
)

const (
	MemberOK      int8 = 1 // 正常
	MemberMerged  int8 = 2 // 被合并
	MemberBlocked int8 = 3 // 封锁

	MemberOKStr      = "ok"      // 正常
	MemberMergedStr  = "merged"  // 被合并
	MemberBlockedStr = "blocked" // 封锁

	MemberUnknow int8 = 0 // 未知
	MemberFemale int8 = 1 // 女
	MemberMale   int8 = 2 //男

	MemberUnknowStr string = "unknow" // 未知
	MemberFemaleStr string = "female" // 女
	MemberMaleStr   string = "male"   //男
)

// MemberRemark 备注信息
type MemberRemark struct {
	MemberMerge map[int64]string `json:"member_merge"`
}

// Member 用户信息
type Member struct {
	Id          int64     `json:"id" sql:"id"`                     // id
	BrandId     int64     `json:"brand_id" sql:"brand_id"`         // 品牌id
	Nickname    string    `json:"nickname" sql:"nickname"`         // 昵称
	Mobile      string    `json:"mobile" sql:"mobile"`             // 手机号
	Email       string    `json:"email" sql:"email"`               // 邮箱
	Gender      int8      `json:"gender" sql:"gender"`             // 性别
	Avatar      string    `json:"avatar" sql:"avatar"`             // 头像
	Birthday    time.Time `json:"birthday" sql:"birthday"`         // 生日
	CountryCode string    `json:"country_code" sql:"country_code"` // 国家码
	Province    string    `json:"province" sql:"province"`         // 省份
	City        string    `json:"city" sql:"city"`                 // 城市
	RegOrigin   string    `json:"reg_origin" sql:"reg_origin"`     // 注册来源
	LoginPasswd string    `json:"login_passwd" sql:"login_passwd"` // 登陆密码
	PayPasswd   string    `json:"pay_passwd" sql:"pay_passwd"`     // 支付密码
	Status      int8      `json:"status" sql:"status"`             // 1~正常 2~被合并 3~封禁
	IsFormal    bool      `json:"is_formal" sql:"is_formal"`       // 是否会员用户
	Remark      []byte    `json:"remark" sql:"remark"`             // 备注
	CreatedAt   time.Time `json:"created_at" sql:"created_at"`
	UpdatedAt   time.Time `json:"updated_at" sql:"updated_at"`
	DeletedAt   int64     `json:"deleted_at" sql:"deleted_at"`
}

// NewMember 新建用户
func NewMember(brandId int64, nickname, mobile, email, gender, avatar, countryCode, province, city, regOrigin string, birthday time.Time) *Member {
	if countryCode == "" {
		countryCode = "86"
	}
	now := util.GetNow()
	return &Member{
		BrandId:     brandId,
		Nickname:    nickname,
		Mobile:      mobile,
		Email:       email,
		Gender:      GetInnerGender(gender),
		Avatar:      avatar,
		Birthday:    birthday,
		CountryCode: countryCode,
		Province:    province,
		City:        city,
		RegOrigin:   regOrigin,
		Status:      MemberOK,
		IsFormal:    false,
		Remark:      []byte("{}"),
		CreatedAt:   now,
		UpdatedAt:   now,
		DeletedAt:   0,
	}
}

func GetInnerGender(g string) int8 {
	switch g {
	case MemberFemaleStr:
		return MemberFemale
	case MemberMaleStr:
		return MemberMale
	default:
		return MemberUnknow
	}
}

// UpdateInfo 更新用户信息
func (m *Member) UpdateInfo(nickname, avatar, province, city string, birthday time.Time) {
	if nickname != "" {
		m.Nickname = nickname
	}
	if avatar != "" {
		m.Avatar = avatar
	}
	m.Province = province
	m.City = city
	if !util.IsZeroTime(birthday) {
		m.Birthday = birthday
	}
	m.UpdatedAt = util.GetNow()
}

// IsValid 是否有效
func (m *Member) IsValid() bool {
	return m.Status == MemberOK && m.DeletedAt == 0
}

// SetStatus 设置状态
func (m *Member) SetStatus(st int8) error {
	status := []int8{MemberOK, MemberMerged, MemberBlocked}
	if !util.ContainInt8(status, st) {
		return InvalidEnum
	}
	m.Status = st
	m.UpdatedAt = util.GetNow()
	return nil
}

// LoginVerify 登陆密码检查
func (m *Member) LoginVerify(password string) bool {
	return m.LoginPasswd == password
}

// PayVerify 支付密码校验
func (m *Member) PayVerify(password string) bool {
	return m.PayPasswd == password
}

// SetGender 设置性别
func (m *Member) SetGender(g string) {
	if g == "" {
		return
	}
	m.Gender = GetInnerGender(g)
	m.UpdatedAt = util.GetNow()
}

// BeFormal 成为正式会员
func (m *Member) BeFormal() {
	if !m.IsFormal {
		m.IsFormal = true
		m.UpdatedAt = util.GetNow()
	}
}

// GetGender 获取性别
func (m *Member) GetGender() string {
	switch m.Gender {
	case MemberFemale:
		return MemberFemaleStr
	case MemberMale:
		return MemberMaleStr
	default:
		return MemberUnknowStr
	}
}

func (m *Member) GetRemark() *MemberRemark {
	remark := &MemberRemark{}
	if m.Remark != nil {
		_ = json.Unmarshal(m.Remark, remark)
	}
	return remark
}

// SetMergeInfo 设置合并备注信息
func (m *Member) SetMergeInfo(memberId int64) {
	remark := m.GetRemark()
	if remark.MemberMerge == nil {
		remark.MemberMerge = map[int64]string{}
	}
	remark.MemberMerge[memberId] = util.TimeStdFormat(util.GetNow())
	m.Remark, _ = json.Marshal(remark)
	m.UpdatedAt = util.GetNow()
}

// UpdateMobile 更新手机号
func (m *Member) UpdateMobile(mobile, countryCode string) {
	if countryCode == "" {
		countryCode = "86"
	}
	m.Mobile = mobile
	m.CountryCode = countryCode
	m.UpdatedAt = util.GetNow()
}

// GetStatus 获取状态
func (m *Member) GetStatus() string {
	switch m.Status {
	case MemberOK:
		return MemberOKStr
	case MemberMerged:
		return MemberMergedStr
	case MemberBlocked:
		return MemberBlockedStr
	default:
		return ""
	}
}

// ConsumptionStatistic 会员消费统计
type ConsumptionStatistic struct {
	// 会员id
	MemberId int64 `json:"member_id" sql:"member_id"`
	// 品牌id
	BrandId int64 `json:"brand_id" sql:"brand_id"`
	// 消费次数
	Count uint32 `json:"count" sql:"count"`
	// 总消费额
	MoneyAmount int64 `json:"money_amount" sql:"money_amount"`
	// 首次消费时间
	CreatedAt time.Time `json:"created_at" sql:"created_at"`
	// 最近消费时间
	UpdatedAt time.Time `json:"updated_at" sql:"updated_at"`
}

// AddConsumptionStatistic 新增会员消费统计
func AddConsumptionStatistic(memberId, brandId int64, amount uint64) *ConsumptionStatistic {
	now := util.GetNow()
	return &ConsumptionStatistic{
		MemberId:    memberId,
		BrandId:     brandId,
		Count:       1,
		MoneyAmount: int64(amount),
		CreatedAt:   now,
		UpdatedAt:   now,
	}
}

// RollbackConsumptionStatistic 回滚消费统计
func RollbackConsumptionStatistic(memberId, brandId int64, amount uint64) *ConsumptionStatistic {
	now := util.GetNow()
	return &ConsumptionStatistic{
		MemberId:    memberId,
		BrandId:     brandId,
		Count:       0,
		MoneyAmount: -int64(amount),
		CreatedAt:   now,
		UpdatedAt:   now,
	}
}
